package iss.java.list;

/**
 * Created by wenke on 2016/9/16.
 * Modified by WeiZehao on 2016/9/30
 */

import iss.java.list.ExceptionA;

public class MyList
{
    // two guards. Do not call remove() on them!!
    private Node head;
    private Node tail;
    private int size;

    public MyList()
    {
        head = new Node(this).setData(0);
        tail = new Node(this).setData(0).setNext(null).setPrev(head);
        head.setNext(tail);
        size = 0;
    }

    public int getSize()
    {
        return size;
    }

    public Node getHead()
    {
        return head;
    }

    public Node getTail()
    {
        return tail;
    }

    /**
     * Insert a node with <pre>data</pre> after <pre>_prev</pre>.
     *
     * @param _prev
     * @param data
     * @return The node just inserted.
     */

    /*插入函数*/
    public Node insert(Node _prev, int data) throws ExceptionA
    {
        if(_prev.getBelong() == this)   // 验证被操作的节点与当前链表是否匹配
        {
            // 给插入位置前面的Node上写锁
            _prev.mylock.writeLock().lock();
            Node node = new Node(this);

            try
            {
                node.setData(data).setNext(_prev.getNext()).setPrev(_prev);
                _prev.getNext().setPrev(node);
                _prev.setNext(node);
                // 保护size。当多线程同时调用insert时，需要保护++size这一计算过程
                synchronized (this)
                {
                    ++size;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                _prev.mylock.writeLock().unlock();
                return node;
            }
        }// end if
        else
        {
            //若被操作节点与当前链表不匹配，抛出异常
            throw new ExceptionA("请不要操作属于其他链表的节点");
        }// end else
    }// end method insert

    /**
     * Remove the node <pre>target</pre>.
     *
     * @param target The node to remove.
     * @return the previous node of target.
     */

    /*删除函数*/
    public Node remove(Node target) throws ExceptionA
    {
        if(target.getBelong() == this)    // 验证被操作的节点与当前链表是否匹配
        {
            // 给被删的节点上写锁
            target.mylock.writeLock().lock();
            if (target == head || target == tail)
            {
                throw new RuntimeException("DO NOT remove the head or tail node. They are guards.");
            }

            // shortcut "target"
            Node prev = target.getPrev();
            Node next = target.getNext();
            try
            {
                prev.setNext(next);
                next.setPrev(prev);
                target.setPrev(null);
                target.setNext(null);
                // 保护size。当多线程同时调用remove时，需要保护++size这一计算过程
                synchronized (this)
                {
                    --size;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                target.mylock.writeLock().unlock();
            }
            // Unlike C/C++, the memory of "target" is automatically recycled by GC
            // return the previous one because it is quite likely to insert a new node after prev;
            return prev;
        }
        else
        {
            //若被操作节点与当前链表不匹配，抛出异常
            throw new ExceptionA("请不要操作属于其他链表的节点");
        }
    }// end method remove
}// end class MyList
